/**
*
QuickUML; A simple UML tool that demonstrates one use of the
Java Diagram Package
Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package uml.builder;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;
import util.FilteredIterator;
/**
* @class CPlusPlusBuilder
*
* @date 08-20-2001
* @author Eric Crahen
* @version 1.0
*
*/
public class CPlusPlusBuilder extends ObjectBuilder {
protected static final MetaAccessComparator attributeComparator = new MetaAccessComparator();
protected String prefix;
/**
*
*/
public CPlusPlusBuilder(String prefix) {
this.prefix = prefix;
}
/**
*
*/
public void build(Context ctx)
throws BuilderException {
super.build(ctx);
try {
// Create the code for the headers first
for(Iterator i = ctx.getInterfaces(); i.hasNext();) {
MetaClass metaClass = (MetaClass)i.next();
PrintWriter out = getWriter(metaClass, "h");
writeHeader(metaClass, out);
out.flush();
}
for(Iterator i = ctx.getClasses(); i.hasNext();) {
MetaClass metaClass = (MetaClass)i.next();
PrintWriter out = getWriter(metaClass, "h");
writeHeader(metaClass, out);
writeSource(metaClass, getWriter(metaClass, "cc"));
out.flush();
}
} catch(IOException e) { throw new BuilderException("I/O Error: " + e.getMessage()); }
}
/**
* Get an output stream for a class
*/
protected PrintWriter getWriter(MetaClass meta, String ext)
throws IOException {
return new PrintWriter(new FileOutputStream(prefix + "/" + meta.getName() + "." + ext));
}
/**
* Write the header
*/
protected void writeHeader(MetaClass metaClass, PrintWriter out)
throws IOException {
// Write the ifndefs
String def = "_" + metaClass.getName().toUpperCase() + "_H_";
out.println("#ifndef " + def);
out.println("#define " + def + "\n");
// Collect all inheritance infor
Vector v = new Vector();
MetaClass superClass = metaClass.getSuperClass();
if(superClass != null)
v.add(superClass.getName());
for(Iterator i = metaClass.getInterfaces(); i.hasNext();)
v.add(((MetaClass)i.next()).getName());
// Write the includes needed
for(int j=0; j < v.size(); j++)
out.println("#include \"" + v.get(j) + ".h\"");
Vector used = new Vector();
for(Iterator i = new FilteredIterator(metaClass.getAttributes(), MetaAssociation.class); i.hasNext();) {
MetaAttribute attr = (MetaAttribute)i.next();
String name = attr.getType();
if(!v.contains(name) && !used.contains(name)) {
out.println("#include \"" + name + ".h\"");
used.add(name);
}
}
// Write declaration
out.print("\nclass " + metaClass.getName());
int sz = v.size();
if(sz > 0) {
out.print(" : public " + v.get(0));
for(int j=1; j < sz; j++)
out.print(", public " + v.get(j));
}
out.print(" {\n");
// Write the attributes if this is a class
if(!metaClass.isInterface())
writeHeaderAttributes(metaClass, out);
// Write the methods
writeHeaderMethods(metaClass, out);
out.println("};\n");
out.println("#endif // " + def);
}
/**
* Write the attributes
*/
protected void writeHeaderAttributes(MetaClass metaClass, PrintWriter out)
throws IOException {
// Collect & sort all the attributes
Vector v = new Vector();
for(Iterator i = metaClass.getAttributes(); i.hasNext();)
v.add(i.next());
Collections.sort(v, attributeComparator);
int n, last = 0;
for(int j=0; j < v.size(); j++) {
MetaAttribute attr = (MetaAttribute)v.get(j);
// C's default acces is private, so clarify it in the header
n = (attr.getAccess() & ~(MetaAccess.ABSTRACT | MetaAccess.STATIC));
if(n == 0)
n = MetaAccess.PRIVATE;
if(last != n) {
last = n;
out.println(MetaAccess.toString(n) + ":\n");
}
out.println("\t" + attr.getType() + " " + attr.getName() + ";");
}
out.print("\n");
}
/**
* Write the attributes section, with a little space in between top and bottom
*/
protected void writeHeaderMethods(MetaClass metaClass, PrintWriter out)
throws IOException {
// Collect & sort all the methods
int last = MetaAccess.PUBLIC;
out.println("public: ");
Vector v = new Vector();
for(Iterator i = metaClass.getMethods(); i.hasNext();) {
Object o = i.next();
if(o instanceof MetaConstructor)
writeHeaderConstructor(metaClass, (MetaConstructor)o, out);
else
v.add(o);
}
// Write a descrutor
writeHeaderDestructor(metaClass, out);
int n;
for(int j=0; j < v.size(); j++) {
MetaMethod meth = (MetaMethod)v.get(j);
// C's default acces is private, so clarify it in the header
n = (meth.getAccess() & ~(MetaAccess.ABSTRACT | MetaAccess.STATIC));
if(n == 0)
n = MetaAccess.PRIVATE;
if(last != n) {
last = n;
out.println("\n" + MetaAccess.toString(n) + ":\n");
}
String signature = meth.getType() + " " + meth.getName() + "(" + MetaParameter.toString(meth) + ")";
if(meth.hasExceptions())
signature += " throw(" + MetaException.toString(meth) + ")";
if(metaClass.isInterface())
out.println("\tvirtual " + signature + " = 0;");
else {
if(MetaAccess.isAbstract(meth.getAccess()))
signature = "virtual " + signature + " = 0";
else if(MetaAccess.isStatic(meth.getAccess()))
signature = "static " + signature;
out.println("\t" + signature + ";");
}
}
out.print("\n");
}
/**
*/
protected void writeHeaderDestructor(MetaClass metaClass, PrintWriter out)
throws IOException {
out.print("\tvirtual ~" + metaClass.getName() + "()");
out.println(metaClass.isInterface() ? " {};" : ";");
}
/**
*/
protected void writeHeaderConstructor(MetaClass metaClass, MetaConstructor cons, PrintWriter out)
throws IOException {
String signature = metaClass.getName() + "(" + MetaParameter.toString(cons) + ")";
if(cons.hasExceptions())
signature += " throw(" + MetaException.toString(cons) + ")";
out.print("\t" + signature);
out.println(metaClass.isInterface() ? " {};" : ";");
}
/**
*/
protected void writeSource(MetaClass metaClass, PrintWriter out)
throws IOException {
out.println("#include \"" + metaClass.getName() + ".h\"\n");
boolean writtenDestructor = false;
for(Iterator i = metaClass.getMethods(); i.hasNext();) {
MetaMethod method = (MetaMethod)i.next();
if(method instanceof MetaConstructor)
writeSourceConstructor(metaClass, (MetaConstructor)method, out);
else {
if(!writtenDestructor) {
writtenDestructor = true;
writeSourceDestructor(metaClass, out);
}
out.print(method.getType() + " " + metaClass.getName() + "::" + method.getName());
out.print("(" + MetaParameter.toString(method) + ")");
if(method.hasExceptions())
out.print(" throw(" + MetaException.toString(method) + ")");
out.print(" { \n\n");
out.print("}\n\n");
}
}
out.flush();
}
/**
*/
protected void writeSourceConstructor(MetaClass metaClass, MetaConstructor cons, PrintWriter out)
throws IOException {
out.print(metaClass.getName() + "::" + metaClass.getName());
out.print("(" + MetaParameter.toString(cons) + ")");
if(cons.hasExceptions())
out.print(" throw(" + MetaException.toString(cons) + ")");
// Write an initializations
int n = 0;
for(Iterator i = cons.getAssociations(), j = cons.getParameters(); i.hasNext();) {
MetaAttribute attr = (MetaAttribute)i.next();
MetaParameter param = (MetaParameter)j.next();
if(n++ == 0)
out.print("\n\t: ");
else
out.print(", ");
out.print(attr.getName());
out.print("(" + param.getName() + ")");
}
// Write the constructor body
out.println(" {\n");
for(Iterator i = cons.getCompositions(); i.hasNext();) {
MetaAttribute attr = (MetaAttribute)i.next();
out.println("\t" + attr.getName() + " = new " + attr.getType() + "();");
}
out.println("\n}\n");
}
/**
*/
protected void writeSourceDestructor(MetaClass metaClass, PrintWriter out)
throws IOException {
out.println(metaClass.getName() + "::~" + metaClass.getName() + "{\n");
for(Iterator i = new FilteredIterator(metaClass.getAttributes(), MetaComposition.class); i.hasNext();) {
MetaAttribute attr = (MetaAttribute)i.next();
out.println("\tdelete " + attr.getName() + ";");
}
out.println("\n}\n");
}
}